﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jbe.TestSuite.Infrastructure.Interface;
using System.Windows.Media;
using System.ComponentModel;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.Security.Authentication;
using Jbe.Composite.Extensions;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Reflection;
using Jbe.TestSuite.Message.Demo.Domain;
using Jbe.TestSuite.Message.Demo.Properties;

namespace Jbe.TestSuite.Message.Demo.Applications
{
    internal class DemoPresentationModel : PresentationModel<IDemoView>, IHeaderInfoProvider
    {
        private static readonly PropertyInfo MessageTypeProperty = TypeManager.GetProperty<DemoPresentationModel>(x => x.MessageType);
        private static readonly PropertyInfo MessageProperty = TypeManager.GetProperty<DemoPresentationModel>(x => x.Message);
        private static readonly PropertyInfo DetailsProperty = TypeManager.GetProperty<DemoPresentationModel>(x => x.Details);
        private static readonly PropertyInfo ThrowExceptionOptionProperty = TypeManager.GetProperty<DemoPresentationModel>(x => x.ThrowExceptionOption);
        private static readonly PropertyInfo ThrowAuthenticationExceptionOptionProperty = TypeManager.GetProperty<DemoPresentationModel>(x => x.ThrowAuthenticationExceptionOption);


        private readonly IMessageService messageService;
        private readonly IStatusMessageService statusMessageService;
        private MessageType messageType;
        private string message = "";
        private string details = "";
        private IThrowExceptionStrategy throwExceptionStrategy = ThrowDefaultException.Instance;
        private DelegateCommand showDialogCommand;
        private DelegateCommand showStatusBarCommand;
        private DelegateCommand throwExceptionCommand;


        public DemoPresentationModel(IDemoView view, IMessageService messageService, IStatusMessageService statusMessageService)
            : base(view)
        {
            this.messageService = messageService;
            this.statusMessageService = statusMessageService;

            showDialogCommand = new DelegateCommand(ShowDialog);
            showStatusBarCommand = new DelegateCommand(ShowStatusBar);
            throwExceptionCommand = new DelegateCommand(ThrowSelectedException);
        }


        public string HeaderInfo
        {
            get { return Resources.MessageDemo; }
        }

        public ImageSource HeaderIcon
        {
            get { return new BitmapImage(ResourceService.GetPackUri("Resources/Message.png")); }
        }

        public MessageType MessageType
        {
            get { return messageType; }
            set
            {
                if (messageType != value)
                {
                    messageType = value;
                    RaisePropertyChanged(MessageTypeProperty);
                }
            }
        }

        public string Message
        {
            get { return message; }
            set
            {
                if (message != value)
                {
                    message = value;
                    RaisePropertyChanged(MessageProperty);
                }
            }
        }

        public string Details
        {
            get { return details; }
            set
            {
                if (details != value)
                {
                    details = value;
                    RaisePropertyChanged(DetailsProperty);
                }
            }
        }

        public bool ThrowExceptionOption
        {
            get { return throwExceptionStrategy == ThrowDefaultException.Instance; }
            set
            {
                if (ThrowExceptionOption != value)
                {
                    throwExceptionStrategy = (value) ? ThrowDefaultException.Instance : null;
                    RaiseOptionPropertiesChanged();
                }
            }
        }

        public bool ThrowAuthenticationExceptionOption
        {
            get { return throwExceptionStrategy == ThrowAuthenticationException.Instance; }
            set
            {
                if (ThrowAuthenticationExceptionOption != value)
                {
                    throwExceptionStrategy = (value) ? ThrowAuthenticationException.Instance : null;
                    RaiseOptionPropertiesChanged();
                }
            }
        }

        public ICommand ShowDialogCommand { get { return showDialogCommand; } }

        public ICommand ShowStatusBarCommand { get { return showStatusBarCommand; } }

        public ICommand ThrowExceptionCommand { get { return throwExceptionCommand; } }


        private void ShowDialog()
        {
            switch (MessageType)
            {
                case MessageType.Information:
                    messageService.ShowInformation(Message, Details);
                    break;
                case MessageType.Warning:
                    messageService.ShowWarning(Message, Details);
                    break;
                case MessageType.Error:
                    messageService.ShowError(Message, Details);
                    break;
            }
        }

        private void ShowStatusBar()
        {
            statusMessageService.UpdateMessage(message);
        }

        private void ThrowSelectedException()
        {
            throwExceptionStrategy.ThrowException();
        }

        private void RaiseOptionPropertiesChanged()
        {
            RaisePropertyChanged(ThrowExceptionOptionProperty);
            RaisePropertyChanged(ThrowAuthenticationExceptionOptionProperty);
        }
    }


    internal interface IThrowExceptionStrategy
    {
        void ThrowException();
    }


    internal class ThrowDefaultException : IThrowExceptionStrategy
    {
        public static readonly ThrowDefaultException Instance = new ThrowDefaultException();


        private ThrowDefaultException() { }


        public void ThrowException()
        {
            throw new Exception();
        }
    }


    internal class ThrowAuthenticationException : IThrowExceptionStrategy
    {
        public static readonly ThrowAuthenticationException Instance = new ThrowAuthenticationException();


        private ThrowAuthenticationException() { }


        public void ThrowException()
        {
            throw new AuthenticationException();
        }
    }
}
